home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Games
/
connx-1.0
/
server.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-25
|
17KB
|
686 lines
/*
* server for connx
*/
#include <sys/signal.h>
#include "connect.h"
#include "commun.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#define TRUE 1
#define FALSE 0
#ifdef AIX
#include <sys/select.h>
#endif
#define BUF_SIZ 255
/* program argument list */
#define NUM_FLAGS 5
enum
{
F_ROWS, F_COLS, F_CONN, F_GAME, F_TIMEOUT
};
int flags_val[] =
{F_ROWS, F_COLS, F_CONN, F_GAME, F_TIMEOUT};
char *flags_txt[] =
{"-rows", "-cols", "-conn", "-gravity", "-timeout"};
/*globals */
int sock;
msg_conn connections;
game_start game_attr;
/* prototypes */
void usage (char *prog);
int parse_args (int argc, char **argv, int *num_rows,
int *num_columns, int *num_to_connect,
int *game_type, int *timeout);
int to_flag (char *string);
void play_game ();
void let_connect ();
void compress_conn ();
void print_choices_before_game ();
void print_choices_during_game ();
int handle_choices_before_game ();
int handle_choices_during_game ();
void server_exit ();
/*****************************************************************************/
main (int argc, char **argv)
{
int i, j;
int rc;
/* set defaults */
game_attr.num_rows = DEF_ROW;
game_attr.num_columns = DEF_COL;
game_attr.num_connect = DEF_CONNECT;
game_attr.game_type = DEF_GAME;
game_attr.timeout = DEF_TIMEOUT;
/* read from command line */
if (parse_args (argc, argv, &game_attr.num_rows, &game_attr.num_columns,
&game_attr.num_connect, &game_attr.game_type,
&game_attr.timeout) == -1)
{
usage (argv[0]);
exit (1);
}
/* clean up nicely on kill */
signal (SIGINT, server_exit);
rc = server_open_socket (&sock);
if (rc != 0)
{
perror ("cannot open socket\n");
exit (1);
}
connections.number_of_conn = 0;
while (1)
{
print_choices_before_game ();
printf ("Choice: ");
fflush (stdout);
let_connect ();
print_choices_during_game ();
printf ("Choice: ");
fflush (stdout);
play_game ();
}
}
/*****************************************************************************/
/*internals*******************************************************************/
/*****************************************************************************/
void
print_choices_before_game ()
{
printf ("\n");
printf ("************************************************************\n");
printf ("* Welcome to connX *\n");
printf ("* Choices: *\n");
printf ("* *\n");
printf ("* h: print this menu *\n");
printf ("* l: list players connected *\n");
printf ("* k: kill a player *\n");
printf ("* s: start the game *\n");
printf ("* c: change game attributes *\n");
printf ("* a: list the game attributes *\n");
printf ("* t: assign players to a team *\n");
printf ("* w: swap position of 2 players *\n");
printf ("* x: exit the program *\n");
printf ("************************************************************\n");
printf ("\n\n");
}
/*****************************************************************************/
int
handle_choices_before_game ()
{
char ret, c, buf[BUF_SIZ];
int pn, pn2, tn, temp, i, rc;
char temp_name[NAME_SIZE];
bzero (buf, BUF_SIZ);
scanf ("%[^\n]", buf);
scanf ("%c", &ret);
c = buf[0];
switch (c)
{
case 'h':
print_choices_before_game ();
break;
case 'l':
compress_conn ();
if (connections.number_of_conn == 0)
printf ("No connections\n");
else
for (i = 0; i < connections.number_of_conn; i++)
printf ("Player %d: %s: team: %d\n", i + 1, game_attr.players[i],
game_attr.team_numbers[i]);
break;
case 'k':
printf ("Player number[1-%d]: ", connections.number_of_conn);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &pn);
if (pn >= 0 && pn <= connections.number_of_conn)
{
close_socket (&connections.conns[pn - 1]);
compress_conn ();
}
}
break;
case 's':
return 1;
break;
case 'c':
printf ("Number of rows[%d]: ", game_attr.num_rows);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &temp);
if (temp > 0 && temp <= MAX_ROW)
game_attr.num_rows = temp;
}
printf ("Number of columns[%d]: ", game_attr.num_columns);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &temp);
if (temp > 0 && temp <= MAX_COL)
game_attr.num_columns = temp;
}
printf ("Number to connect[%d]: ", game_attr.num_connect);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &temp);
if (temp > 0 && temp <= MAX_CONNECT)
game_attr.num_connect = temp;
}
printf ("Game type (%d=gravity %d=nogravity) [%d]: ", GRAVITY, NOGRAVITY,
game_attr.game_type);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &temp);
if (temp == GRAVITY || temp == NOGRAVITY)
game_attr.game_type = temp;
}
printf ("Timeout[%d]: ", game_attr.timeout);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &temp);
if (temp >= 0)
game_attr.timeout = temp;
}
break;
case 'a':
printf ("Number of rows: %d\n", game_attr.num_rows);
printf ("Number of columns: %d\n", game_attr.num_columns);
printf ("Number to connect: %d\n", game_attr.num_connect);
printf ("Game type (%d=gravity %d=nogravity): %d\n",
GRAVITY, NOGRAVITY, game_attr.game_type);
printf ("Timeout: %d\n", game_attr.timeout);
break;
case 't':
printf ("Player number[1-%d]: ", connections.number_of_conn);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &pn);
printf ("Team number[1-%d]: ", connections.number_of_conn);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &tn);
if (pn >= 1 && tn >= 1 && pn <= connections.number_of_conn
&& tn <= connections.number_of_conn)
game_attr.team_numbers[pn - 1] = tn;
}
}
break;
case 'w':
printf ("First player[1-%d]: ", connections.number_of_conn);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &pn);
printf ("Second player[1-%d]: ", connections.number_of_conn);
rc = scanf ("%[^\n]", buf);
scanf ("%c", &ret);
if (rc != 0)
{
sscanf (buf, "%d", &pn2);
if (pn >= 1 && pn2 >= 1 && pn <= connections.number_of_conn &&
pn2 <= connections.number_of_conn)
{
temp = game_attr.team_numbers[pn - 1];
game_attr.team_numbers[pn - 1] = game_attr.team_numbers[pn2 - 1];
game_attr.team_numbers[pn2 - 1] = temp;
temp = connections.conns[pn - 1];
connections.conns[pn - 1] = connections.conns[pn2 - 1];
connections.conns[pn2 - 1] = temp;
strcpy (temp_name, game_attr.players[pn - 1]);
strcpy (game_attr.players[pn - 1], game_attr.players[pn2 - 1]);
strcpy (game_attr.players[pn2 - 1], temp_name);
}
}
}
break;
case 'x':
return -1;
break;
default:
print_choices_before_game();
break;
}
printf ("Choice: ");
fflush (stdout);
return 0;
}
/*****************************************************************************/
void
print_choices_during_game ()
{
printf ("\n");
printf ("************************************************************\n");
printf ("* Game In Progress *\n");
printf ("* Choices: *\n");
printf ("* *\n");
printf ("* h: print this menu *\n");
printf ("* x: stop the game *\n");
printf ("************************************************************\n");
printf ("\n\n");
}
/*****************************************************************************/
int
handle_choices_during_game ()
{
char ret, c, buf[BUF_SIZ];
int rc = 0;
bzero (buf, BUF_SIZ);
scanf ("%[^\n]", buf);
scanf ("%c", &ret);
c = buf[0];
switch (c)
{
case 'h':
print_choices_during_game ();
break;
case 'x':
rc = -1;
break;
default:
print_choices_during_game();
break;
}
printf ("Choice: ");
fflush (stdout);
return rc;
}
/****************************************************************************/
/*
* get rid of any closed connections and compress player list
*/
void
compress_conn ()
{
int i, j, used, team;
for (i = 0; i < connections.number_of_conn; i++)
if (check_status (&connections.conns[i]) == -1)
{
team = game_attr.team_numbers[i];
for (j = i; j < connections.number_of_conn - 1; j++)
{
connections.conns[j] = connections.conns[j + 1];
strcpy (game_attr.players[j], game_attr.players[j + 1]);
game_attr.team_numbers[j] = game_attr.team_numbers[j + 1];
}
connections.number_of_conn--;
/* check if anyone else is using the team number */
used = 0;
for (j = 0; j < connections.number_of_conn; j++)
if (game_attr.team_numbers[j] == team)
used = 1;
/* if no one is using it, compress team numbers */
if (used == 0)
for (j = 0; j < connections.number_of_conn; j++)
if (game_attr.team_numbers[j] > team)
game_attr.team_numbers[j]--;
/* check the connection i has been replaced with */
i--;
}
}
/*****************************************************************************/
void
let_connect ()
{
char pick;
int rc, i, num;
gen_msg msg_recv;
char recv_arr[512];
new_player *add_player_msg;
struct fd_set readfs;
int used, unused;
compress_conn ();
msg_recv.msg = (char *) recv_arr;
/* let the players connect */
while (1)
{
FD_ZERO (&readfs);
FD_SET (0, &readfs); /*stdin*/
FD_SET (sock, &readfs);
if ((num = select (sock + 1, &readfs, NULL, NULL, NULL)) < 0)
{
printf ("select error\n");
exit (1);
}
if (FD_ISSET (sock, &readfs))
{ /* new players connects */
compress_conn ();
rc = server_accept_connection (sock, &connections);
if (rc != -1)
{
rc = read_message (&connections.conns[connections.
number_of_conn - 1],
&msg_recv);
if (rc == -1 || msg_recv.msg_type != NEW_PLAYER)
{
close_socket
(&connections.conns[connections.number_of_conn]);
connections.number_of_conn--;
}
else
{
add_player_msg = (new_player *) msg_recv.msg;
strcpy (game_attr.players[connections.number_of_conn - 1],
add_player_msg->name);
/* find unused team number */
unused = 0;
used = 1;
while (used == 1)
{
unused++;
used = 0;
for (i = 0; i < (connections.number_of_conn - 1); i++)
if (game_attr.team_numbers[i] == unused)
used = 1;
}
game_attr.team_numbers[connections.number_of_conn - 1]
= unused;
printf ("\nplayer %s added.\n", add_player_msg->name);
printf ("Choice: ");
fflush (stdout);
}
}
}
if (FD_ISSET (0, &readfs))
{ /* request from stdin */
rc = handle_choices_before_game ();
if (rc == 1)
break; /* start game */
else if (rc == -1)
server_exit ();
}
}
compress_conn ();
}
/*****************************************************************************/
void
play_game ()
{
int i, j;
int rc;
game_end game_end;
gen_msg msg_recv;
char recv_arr[MAX_DATA];
int game_over = FALSE;
int got_move;
my_move *move;
others_move others_move;
int still_out_there;
int num_players;
whose_move whose;
struct fd_set readfs;
msg_recv.msg = (char *) recv_arr;
num_players = connections.number_of_conn;
game_attr.num_players = num_players;
if (connections.number_of_conn == 0)
{
printf ("No players\n");
return;
}
allocate (game_attr.game_type, game_attr.num_rows, game_attr.num_columns,
num_players, game_attr.num_connect);
/* tell players game is to start */
for (i = 0; i < num_players; i++)
{
game_attr.your_number = i + 1;
rc = send_message (&connections.conns[i], GAME_START,
sizeof (game_attr), (char *) &game_attr);
}
/*play the game*/
while (game_over == FALSE)
{
still_out_there = 0;
for (i = 0; i < connections.number_of_conn; i++)
{
/* alert person whose turn it is */
rc = send_message (&connections.conns[i], YOUR_MOVE,
0, (char *) NULL);
if (rc != -1)
{
still_out_there = 1;
/* tell everyone whose move it is*/
whose.player = i + 1;
for (j = 0; j < connections.number_of_conn; j++)
if (j != i)
send_message (&connections.conns[j], WHOSE_MOVE,
sizeof (whose_move), (char *) &whose);
/* get move and handle stdin*/
got_move = FALSE;
while (got_move == FALSE)
{
FD_ZERO (&readfs);
FD_SET (0, &readfs); /*stdin*/
FD_SET (connections.conns[i], &readfs);
select (connections.conns[i] + 1, &readfs, NULL, NULL, NULL);
if (FD_ISSET (connections.conns[i], &readfs))
got_move = TRUE;
if (FD_ISSET (0, &readfs))
if (handle_choices_during_game () == -1)
{
game_end.winner = CANCEL_GAME;
game_over = TRUE;
/* tell client to abandon his move */
send_message (&connections.conns[i], CANCEL_MOVE, 0, NULL);
}
}
rc = read_message (&connections.conns[i], &msg_recv);
if (rc != -1 && msg_recv.msg_type == MY_MOVE)
{
move = (my_move *) msg_recv.msg;
if (move->move.row != FORFEIT ||
move->move.column != FORFEIT)
{
move->rc = add_to_board (&(move->move),
game_attr.team_numbers[i]);
rc = send_message (&connections.conns[i], MY_MOVE,
sizeof (my_move), (char *) move);
if (move->rc == -1 && rc == 0)
i--;
}
else
move->rc = -1;
}
else
close_socket (&connections.conns[i]);
if (rc == 0 && move->rc == 0)
{
/* tell everyone the move*/
others_move.player_number = i + 1;
others_move.move = move->move;
for (j = 0; j < connections.number_of_conn; j++)
send_message (&connections.conns[j],
OTHERS_MOVE, sizeof (others_move),
(char *) &others_move);
rc = check_for_win (move->move, &game_end.connect[0],
&game_end.connect[1]);
if (rc == 0)
{
game_over = TRUE;
game_end.winner = i + 1;
}
rc = check_for_tie ();
if (rc == 0)
{
game_over = TRUE;
game_end.winner = TIE_GAME;
}
}
if (game_over == TRUE)
break;
}
}
if (still_out_there == 0)
{
/* No one left in the game */
return;
}
}
/* tell everyone game is over */
for (j = 0; j < connections.number_of_conn; j++)
send_message (&connections.conns[j], GAME_END, sizeof (game_end),
(char *) &game_end);
}
/***************************************************************************/
/*
* command line processing
*/
int
parse_args (int argc, char **argv, int *num_rows,
int *num_columns, int *num_to_connect,
int *game_type, int *timeout)
{
int i;
int flag;
if (((argc - 1) % 2) != 0)
return -1;
for (i = 1; i < argc; i = i + 2)
{
flag = to_flag (argv[i]);
switch (flag)
{
case F_ROWS:
*num_rows = atoi (argv[i + 1]);
break;
case F_COLS:
*num_columns = atoi (argv[i + 1]);
break;
case F_CONN:
*num_to_connect = atoi (argv[i + 1]);
break;
case F_GAME:
if (strcmp (argv[i + 1], "yes") == 0)
*game_type = GRAVITY;
else if (strcmp (argv[i + 1], "no") == 0)
*game_type = NOGRAVITY;
else
return -1;
break;
case F_TIMEOUT:
*timeout = atoi (argv[i + 1]);
break;
default:
return -1;
break;
}
}
return 0;
}
/*****************************************************************************/
int
to_flag (char *string)
{
int i;
for (i = 0; i < NUM_FLAGS; i++)
if (strcmp (string, flags_txt[i]) == 0)
return flags_val[i];
return -1;
}
/*****************************************************************************/
void
usage (char *prog)
{
int i;
printf ("Usage: %s \n", prog);
printf ("-rows <num_rows>\n");
printf ("-cols <num_cols>\n");
printf ("-conn <num_to_connect>\n");
printf ("-gravity <yes or no>\n");
printf ("-timeout <num>\n\n");
}
/*****************************************************************/
void
server_exit ()
{
int i;
for (i = 0; i < connections.number_of_conn; i++)
close_socket (&connections.conns[i]);
close_socket (&sock);
printf ("\n");
exit (0);
}